package com.starsky.common.utils.os;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @desc: 获取系统的信息
 * @author: wangsh
 * @time: 2020/10/14 8:38
 */
@Slf4j
public final class SystemUtils {

    private static final String[] HEADERS_TO_TRY = {"X-Forwarded-For",
            "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED", "HTTP_X_CLUSTER_CLIENT_IP", "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR", "HTTP_FORWARDED", "HTTP_VIA", "REMOTE_ADDR",
            "X-Real-IP"};

    /**
     * 获取访问者IP
     * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
     * <p>
     * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
     * 如果还不存在则调用Request .getRemoteAddr()。
     *
     * @param request
     * @return
     */
    public static String getClientIpAddress(HttpServletRequest request) {
        for (String header : HEADERS_TO_TRY) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0
                    && !"unknown".equalsIgnoreCase(ip)) {
                return ip;
            }
        }
        return request.getRemoteAddr();
    }

    /**
     * 获取访问者IP
     * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
     * <p>
     * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
     * 如果还不存在则调用Request .getRemoteAddr()。
     *
     * @param request
     * @return
     */
    public static String getRemoteAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }


    /**
     * 通过ip地址获取mac地址
     *
     * @param ip
     * @return
     */
    public static String getMacAddrByIp(String ip) {
        String macAddr = null;
        try {
            Process process = Runtime.getRuntime().exec("nbtstat -a " + ip);
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            Pattern pattern = Pattern.compile("([A-F0-9]{2}-){5}[A-F0-9]{2}");
            Matcher matcher = null;
            for (String strLine = br.readLine(); strLine != null; strLine = br.readLine()) {
                matcher = pattern.matcher(strLine);
                if (matcher.find()) {
                    macAddr = matcher.group();
                    break;
                }
            }
        } catch (IOException e) {
            log.error("通过ip地址获取mac地址异常![{}]", e.getMessage());
        }
        System.out.println(macAddr);
        return macAddr;
    }

    /**
     * 获取本机的ip
     *
     * @return
     */
    public static String getLocalIp(String ipStartWith) {
        try {
            Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = (InetAddress) addresses.nextElement();
                    if (ip != null && ip instanceof Inet4Address) {
                        String ipStr = ip.getHostAddress();
                        if (ipStr.startsWith(ipStartWith)) {
                            return ipStr;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取本机ip异常![{}]", e.getMessage());
            return "";
        }
        return "";
    }

    /**
     * 获取本机ip地址，兼容linux本方法
     */
    public static String getLocalIp() {
        Enumeration allNetInterfaces;
        try {
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            String ipAddress = "";
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                log.debug("netInterface.getName:[{}]", netInterface.getName());
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = (InetAddress) addresses.nextElement();
                    if (ip != null && ip instanceof Inet4Address) {
                        ipAddress = ip.getHostAddress();
                    }
                }
            }
            return ipAddress;
        } catch (SocketException e) {
            log.error("获取本机ip异常![{}]", e.getMessage());
            return "";
        }
    }

    /**
     * 获取本机ip地址，兼容linux本方法
     */
    public static List<String> getLocalIps() {
        List<String> ips = new ArrayList<>();
        try {
            Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                log.debug("netInterface.getName:[{}]", netInterface.getName());
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress ip = (InetAddress) addresses.nextElement();
                    String ipAddress = ip.getHostAddress();
                    ips.add(ipAddress);
                }
            }
        } catch (SocketException e) {
            log.error("获取本机ip异常![{}]", e.getMessage());
        }
        return ips;
    }


    /**
     * 获取mac地址
     *
     * @param request
     * @return
     */
    public static String getRemoteMac(HttpServletRequest request) {
        String str;
        String macAddress = "";
        String ip = getRemoteAddr(request);
        try {
            Process p = Runtime.getRuntime().exec("nbtstat -a " + ip);
            InputStreamReader ir = new InputStreamReader(p.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            for (int i = 1; i < 100; ++i) {
                str = input.readLine();
                if (str != null && str.indexOf("MAC") > 1) {
                    macAddress = str.substring(str.indexOf("=") + 2, str.length());
                    break;
                }
            }
        } catch (IOException var8) {
            var8.printStackTrace(System.out);
        }
        return macAddress;
    }

    /**
     * 获取来访者的浏览器版本
     *
     * @param request
     * @return
     */
    public static String getRequestBrowser(HttpServletRequest request) {
        String browserVersion = null;
        String header = request.getHeader("user-agent");
        if (header == null || header.equals("")) {
            return "";
        }
        if (header.indexOf("MSIE") > 0) {
            browserVersion = "IE";
        } else if (header.indexOf("Firefox") > 0) {
            browserVersion = "Firefox";
        } else if (header.indexOf("Chrome") > 0) {
            browserVersion = "Chrome";
        } else if (header.indexOf("Safari") > 0) {
            browserVersion = "Safari";
        } else if (header.indexOf("Camino") > 0) {
            browserVersion = "Camino";
        } else if (header.indexOf("Konqueror") > 0) {
            browserVersion = "Konqueror";
        }
        return browserVersion;
    }

    /**
     * 获取系统版本信息
     *
     * @param request
     * @return
     */
    public static String getRequestSystemInfo(HttpServletRequest request) {
        String systenInfo = null;
        String header = request.getHeader("user-agent");
        if (header == null || header.equals("")) {
            return "";
        }
        //得到用户的操作系统
        if (header.indexOf("NT 6.0") > 0) {
            systenInfo = "Windows Vista/Server 2008";
        } else if (header.indexOf("NT 5.2") > 0) {
            systenInfo = "Windows Server 2003";
        } else if (header.indexOf("NT 5.1") > 0) {
            systenInfo = "Windows XP";
        } else if (header.indexOf("NT 6.0") > 0) {
            systenInfo = "Windows Vista";
        } else if (header.indexOf("NT 6.1") > 0) {
            systenInfo = "Windows 7";
        } else if (header.indexOf("NT 6.2") > 0) {
            systenInfo = "Windows Slate";
        } else if (header.indexOf("NT 6.3") > 0) {
            systenInfo = "Windows 9";
        } else if (header.indexOf("NT 5") > 0) {
            systenInfo = "Windows 2000";
        } else if (header.indexOf("NT 4") > 0) {
            systenInfo = "Windows NT4";
        } else if (header.indexOf("Me") > 0) {
            systenInfo = "Windows Me";
        } else if (header.indexOf("98") > 0) {
            systenInfo = "Windows 98";
        } else if (header.indexOf("95") > 0) {
            systenInfo = "Windows 95";
        } else if (header.indexOf("Mac") > 0) {
            systenInfo = "Mac";
        } else if (header.indexOf("Unix") > 0) {
            systenInfo = "UNIX";
        } else if (header.indexOf("Linux") > 0) {
            systenInfo = "Linux";
        } else if (header.indexOf("SunOS") > 0) {
            systenInfo = "SunOS";
        }
        return systenInfo;
    }

    /**
     * 获取来访者的主机名称
     *
     * @param ip
     * @return
     */
    public static String getHostName(String ip) {
        InetAddress inet;
        try {
            inet = InetAddress.getByName(ip);
            return inet.getHostName();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 执行命令
     *
     * @param cmd
     * @return
     */
    public static String callCmd(String cmd) {
        String result = "";
        String line = "";
        try {
            Process proc = Runtime.getRuntime().exec(cmd);
            result = readLines(proc);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("执行命令异常：", e.getMessage());
        }
        return result;
    }

    /**
     * 获取文件流结果
     */
    public static String readLines(Process proc) {
        String result = readLines(proc.getInputStream());
        return result;
    }

    /**
     * 获取文件流结果
     */
    public static String readLines(InputStream in) {
        String result = null;
        try {
            String charset = "UTF-8";
            if (OSUtils.isWindows()) charset = "GBK";
            List<String> list = IOUtils.readLines(in, charset);
            result = StringUtils.join(list, "");
//            InputStreamReader is = new InputStreamReader(in);
//            BufferedReader br = new BufferedReader(is);
//            String line = null;
//            while ((line = br.readLine()) != null) {
//                result += line;
//            }
            System.out.println("获取文件流结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取文件流结果异常：", e.getMessage());
        }
        log.info("获取文件流结果: ", result);
        return result;
    }

    /**
     * 执行命令
     *
     * @param cmd
     * @return
     */
    public static String callCmd(String[] cmd) {
        String result = "";
        try {
            Process proc = Runtime.getRuntime().exec(cmd);
            result = readLines(proc);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("执行命令异常：", e.getMessage());
        }
        return result;
    }

    /**
     * @param cmd     第一个命令
     * @param another 第二个命令
     * @return 第二个命令的执行结果
     */

    public static String callCmd(String[] cmd, String[] another) {
        String result = "";
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(cmd);
            proc.waitFor(); // 已经执行完第一个命令，准备执行第二个命令
            proc = rt.exec(another);
            result = readLines(proc);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("执行命令异常：", e.getMessage());
        }
        return result;
    }

    /**
     * @param ip           目标ip,一般在局域网内
     * @param sourceString 命令处理的结果字符串
     * @param macSeparator mac分隔符号
     * @return mac地址，用上面的分隔符号表示
     */
    private static String filterMacAddress(final String ip, final String sourceString, final String macSeparator) {
        String result = "";
        String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
        Pattern pattern = Pattern.compile(regExp);
        Matcher matcher = pattern.matcher(sourceString);
        while (matcher.find()) {
            result = matcher.group(1);
            if (sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {
                break; // 如果有多个IP,只匹配本IP对应的Mac.
            }
        }
        return result;
    }

    /**
     * @param ip 目标ip
     * @return Mac Address
     */
    public static String getMacInWindows(String ip) {
        String result = "";
        String[] cmd = {"cmd", "/c", "ping " + ip};
        String[] another = {"cmd", "/c", "arp -a"};
        String cmdResult = callCmd(cmd, another);
        result = filterMacAddress(ip, cmdResult, "-");
        return result;
    }

    /**
     * @param ip 目标ip
     * @return Mac Address
     */
    public static String getMacInLinux(final String ip) {
        String result = "";
        String[] cmd = {"/bin/sh", "-c", "ping " + ip + " -c 2 && arp -a"};
        String cmdResult = callCmd(cmd);
        result = filterMacAddress(ip, cmdResult, ":");
        return result;
    }

    /**
     * 获取MAC地址
     *
     * @return 返回MAC地址
     */
    public static String getMacAddress(String ip) {
        String macAddress = "";
        macAddress = getMacInWindows(ip).trim();
        if (macAddress == null || "".equals(macAddress)) {
            macAddress = getMacInLinux(ip).trim();
        }
        return macAddress;
    }


    /**
     * 判断客户端浏览器类型
     *
     * @param request
     * @return
     */
    public static String getBrowser(HttpServletRequest request) {
        String UserAgent = request.getHeader("User-Agent").toLowerCase();
        if (UserAgent.indexOf("firefox") >= 0) {
            return "FF";
        } else if (UserAgent.indexOf("safari") >= 0) {
            return "Chrome";
        } else {
            return "IE";
        }
    }

    public static void main(String[] args) {

//        System.out.println("getMacAddress(\"192.168.2.150\") = " + getMacAddress("192.168.2.150"));
        String ip = "192.168.2.150";
//        getMacAddrByIp(ip);
        String dir = SystemUtils.callCmd("cmd /c dir");
        System.out.println("dir: " + dir);

        String cmd[] = new String[]{"cmd", "/c", "dir"};
        String str2 = SystemUtils.callCmd(cmd);
        System.out.println("dir2: " + str2);

        String macInWindows = getMacInWindows(ip);
        System.out.println(macInWindows);
    }
}
